/*
 * Copyright (c) 2023 fred
 * Licensed under the Apache License,Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import { Attributes } from './Attributes';
import { Node } from './Node';
import List from '@ohos.util.List';
import { OutputSettings } from './OutputSettings';

export abstract class LeafNode extends Node {

  public nodeName(): string {
    return ""
  }
  // either a string value, or an attribute map (in the rare case multiple attributes are set)
  value:any
  public hasAttributes():boolean {
    return this.value instanceof Attributes
  }

  public attributes():Attributes {
    this.ensureAttributes()
    return this.value as Attributes
  }

  private ensureAttributes() {
    if (!this.hasAttributes()) {
      let coreValue = this.value
      let attributes = new Attributes()
      this.value = attributes
      if (coreValue !== undefined && coreValue !== null) {
        this.value.put(this.nodeName(),coreValue as string)
      }
    }
  }

  coreValue():string{
    return this.getAttr(this.nodeName())
  }

  setCoreValue(value:string) {
    this.setAttr(this.nodeName(),value)
  }

  public getAttr(key:string):string {
    if (!this.hasAttributes()) {
      return this.nodeName() === key ? this.value as string : Node.EmptyString
    }
    return super.getAttr(key)
  }

  public setAttr(key:string, value:string):Node {
    if (!this.hasAttributes() && key === this.nodeName()) {
      this.value = value
    } else {
      this.ensureAttributes()
      super.setAttr(key,value)
    }
    return this
  }

  public hasAttr(key:string):boolean {
    this.ensureAttributes()
    return super.hasAttr(key)
  }

  public removeAttr(key:string):Node {
    this.ensureAttributes()
    return super.removeAttr(key)
  }

  public absUrl(key:string):string {
    this.ensureAttributes()
    return super.absUrl(key)
  }

  public baseUri():string {
    return this.hasParent() ? this.parent().baseUri() : ""
  }

  public  doSetBaseUri(baseUri:string) {
    //noop
  }

  public childNodeSize():number {
    return 0
  }

  public empty():Node {
    return this
  }

  protected ensureChildNodes(): List<Node> {
    return Node.EmptyNodes
  }

  protected doClone(parent:Node):LeafNode {
    let clone = super.doClone(parent) as LeafNode
    if (this.hasAttributes()) {
      clone.value = (this.value as Attributes).clone()
    }
    return clone
  }
}
